# -*- coding:utf-8 -*- 

from cn.pigersing.PyShare.Event import *
from cn.pigersing.PyShare.Services.ServiceBase import *
from cn.pigersing.PyShare.Services.ServiceExceptions import *
from cn.pigersing.PyShare.Services.Session import *
from cn.pigersing.PyShare.utils.LogPrint import get_logger
from random import choice
from string import printable


# define the code length of secret 
CODE_LENGTH = 16

logger = get_logger('UtilServices')
# don't display the debug information
logger.setLevel(20)


def random_string(length):
    """
    Returns a random string of letters with the given length.
    """
    chars = []
    letters = printable[: - 7]
    
    while length > 0:
        length -= 1
        chars.append(choice(letters))
    return ''.join(chars)


class Authentication(ServiceNode):
    
    
    def __init__(self):
        
        super(Authentication, self).__init__('auth')
        self.public_key = random_string(CODE_LENGTH)
        
    
    @expose
    def join(self, session_src, public_key):
        ''' join to a server, create a new session '''
        
        session = Session.from_xml_string(session_src)
        
        # set session's private key
        private_key = random_string(CODE_LENGTH)
        session.set_crt_key(private_key, public_key)
        
        try:
            self.root.server.add_session(session)
            logger.debug('joined to %s, whose id is:%s' % (session.url, session.id))
            # trigger the event
            dispatch_event(Event('Authentication.Joined',
                                 (session,)))
            
            return self.public_key
        
        except SessionAlreadyExists:
            raise SessionExistsError
        
    
    @expose  
    def leave(self, id, public_key):
        '''remove one session '''

        # get current session
        if id != self.root.server.id and self.root.server.is_contained(id) :
            s = self.root.server.get_session(id)
            if s.verify(public_key):
                self.root.server.remove_session(id)
                logger.debug('leaved one session, whose id is :%s' % id)
                # trigger the leave event
                dispatch_event(Event('Authentication.Leaved',
                                 (s,)))
                
        else :
            return FAULT_BASE
        
        return SUCCESS_BASE  # always returns success
    
        